package com.hunt.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hunt.dao.TransactionCalendarMapper;
import com.hunt.model.app.RealtimeFinancialData;
import com.hunt.model.app.RealtimeFinancialDataInfo;
import com.hunt.model.app.TransactionCalendar;
import com.hunt.model.dto.BuySellEntity;
import com.hunt.model.dto.StockDayDataVO;
import com.hunt.model.dto.StockMinDataVO;
import com.hunt.model.entity.*;
import com.hunt.service.AppStockDataService;
import com.hunt.util.SplitKLineRes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xerial.snappy.Snappy;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

import static com.hunt.util.SystemConstant.*;

/**
 * @author sjs
 * @className
 * @description
 * @date 2020/9/16
 */

@Service
@Transactional
public class AppStockDataServiceImpl implements AppStockDataService {

    private static final Logger logger = LoggerFactory.getLogger(AppStockDataServiceImpl.class);

    @Autowired
    private MongoTemplate stockMongoTemplate;
    @Autowired
    private TransactionCalendarMapper TransactionCalendarMapper;
    @Autowired
    private JedisPool jedisPool;

    @Override
    public HqStockDataInfo getRecentMinDataNew(String symbol) {

        HqStockDataInfo hqStockDataInfo = null;
        Jedis resource = null;
        try {
            resource = jedisPool.getResource();
            List<String> hqStock = resource.hmget("Real_time_Stock_Data", symbol);
            if (hqStock != null && hqStock.get(0) != null) {
                hqStockDataInfo = JSON.parseObject(hqStock.get(0), HqStockDataInfo.class);
            }
        } catch (Exception e) {
            logger.debug("补充当日日K错误:{}",e.getMessage());
            e.printStackTrace();
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
        return hqStockDataInfo;
    }

    @Override
    public RealtimeFinancialData getRealtimeFinancialDataByStockCode(String s) {
        RealtimeFinancialData realtimeFinancialData = new RealtimeFinancialData();
        RealtimeFinancialDataInfo realtimeFinancialDataInfo = new RealtimeFinancialDataInfo();
        LocalDateTime nowLocalTime = LocalDateTime.now();
        String serverTimeStr = nowLocalTime.format(timeFormatter);
        realtimeFinancialData.setServertime(serverTimeStr);
        realtimeFinancialData.setStart(0);
        realtimeFinancialData.setEnd(20);
        realtimeFinancialData.setCount(1);
        realtimeFinancialData.setTicket(1);
        realtimeFinancialData.setVersion("HQ.Stock 2.0");
        realtimeFinancialData.setMessage("加载板块");
        realtimeFinancialData.setCode(0);
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            double exchange = 0;
            double amp = 0;
            List<String> realTimeStockData = jedis.hmget("Real_time_Stock_Data", s);
            List<String> nameStrList = jedis.hmget("Stock_Base_Message", s);
            if (realTimeStockData.get(0) != null) {
                String stockObj = realTimeStockData.get(0);
                StockRealTime stockRealTime = JSON.parseObject(stockObj, StockRealTime.class);
                amp =(stockRealTime.getHigh()-stockRealTime.getLow())/stockRealTime.getPreClose() * 100;
                String stockName = null;
                if (nameStrList.get(0) != null) {
                    String nameStr = nameStrList.get(0);
                    JSONObject stockBaseJson = JSON.parseObject(nameStr);
                    stockName = (String) stockBaseJson.get("name");
                    long sharesObj = stockBaseJson.getLongValue("floatShares");
                    long vol = stockRealTime.getVol();
                    exchange = new BigDecimal(vol).divide(new BigDecimal(sharesObj),10,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).doubleValue() * 100;//换手率
                }
                realtimeFinancialDataInfo.setTime(Integer.valueOf(stockRealTime.getDateTime().substring(8,14)));
                realtimeFinancialDataInfo.setDate(Long.valueOf(stockRealTime.getDateTime().substring(0,8)));
                realtimeFinancialDataInfo.setPrice(stockRealTime.getNewPrice());
                realtimeFinancialDataInfo.setOpen(stockRealTime.getOpen());
                realtimeFinancialDataInfo.setYclose(stockRealTime.getPreClose());
                realtimeFinancialDataInfo.setHigh(stockRealTime.getHigh());
                realtimeFinancialDataInfo.setLow(stockRealTime.getLow());
                realtimeFinancialDataInfo.setVol(stockRealTime.getVol());
                realtimeFinancialDataInfo.setAmount(stockRealTime.getMoney());
                realtimeFinancialDataInfo.setAmplitude(amp);
                realtimeFinancialDataInfo.setIncrease(stockRealTime.getHlPercent().equals("--")?0:Double.valueOf(stockRealTime.getHlPercent().replaceAll("%","")));
                realtimeFinancialDataInfo.setExchangerate(exchange);
                realtimeFinancialDataInfo.setVolratio(0);
                realtimeFinancialDataInfo.setSymbol(s);
                realtimeFinancialDataInfo.setName(stockName);
                realtimeFinancialData.getStock().add(realtimeFinancialDataInfo);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null)
                jedis.close();
        }
        return realtimeFinancialData;
    }

    @Override
    public List<StockSpecialSign> getStockSpecialSign() {
        Jedis jedis=jedisPool.getResource();
        Map<String, String> map=jedis.hgetAll("Stock_Base_Message");
        List<StockSpecialSign> ls=new ArrayList<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            StockSpecialSign stockSpecialSign=JSON.parseObject(entry.getValue(),StockSpecialSign.class);
            stockSpecialSign.setStockCode(entry.getKey());
            ls.add(stockSpecialSign);
        }
        return ls;
    }
    @Override
    public StockSpecialSign getSingleStockSpecialSign(String symbol) {
        Jedis jedis=jedisPool.getResource();
        StockSpecialSign stockSpecialSign=null;
       String sbm=jedis.hget("Stock_Base_Message",symbol);
       if(sbm!=null){
           stockSpecialSign=JSON.parseObject(sbm,StockSpecialSign.class);
       }
       else {
           stockSpecialSign=new StockSpecialSign();
       }
       stockSpecialSign.setStockCode(symbol);

        return stockSpecialSign;
    }
    @Override
    public List<HqStockData> findRecentMinData(String symbol, int limit) {
        List<String> hqStockDataStrList = new ArrayList<>();
        List<HqStockData> hqStockDataList = new ArrayList<>();

        Jedis resource = null;
        try {
            resource = jedisPool.getResource();
//            List<LocalDate> dateList = new ArrayList<>();
//            Set<String> keys = resource.keys("*FB:" + symbol);//*FB:300450.sz
//            Iterator<String> it = keys.iterator();
//            while (it.hasNext()){
//                String key = it.next();
//                try {
//                    dateList.add(LocalDate.parse(key.substring(2,12),LOCAL_DATE_FORMATTER));
//                }catch (Exception e){
//                }
//            }
//            String selectKey = null;
//            if (dateList.size()>=1){
//                Collections.sort(dateList);
//                selectKey = "2021-11-19"+"FB:"+symbol;
//            }else{
//                return hqStockDataList;
//            }

            List<byte[]> recentStockDataList = resource.lrange(Snappy.compress(RecentMinData()+"FB:"+symbol), 0, limit);
            if (recentStockDataList.size() != 0) {

                for (byte[] bytes : recentStockDataList) {
                    String stockData = Snappy.uncompressString(bytes);
                    hqStockDataStrList.add(stockData);
                    hqStockDataList = JSONArray.parseArray(hqStockDataStrList.toString(), HqStockData.class);
                }
            }
        } catch (Exception e) {
            logger.debug("redis中：[]", hqStockDataList.toString());
            e.printStackTrace();
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
        return hqStockDataList;
    }

    @Override
    public BuySellEntity getStockRealTime(String symbol) {
        long startSysTime = System.currentTimeMillis();//获取当前系统时间(毫秒)
        StockRealTime stockRealTimeData = new StockRealTime();
        Jedis resource = jedisPool.getResource();
        BuySellEntity mData = new BuySellEntity();
        try {
            double c = 0;
            double amp = 0;
            List<String> realTimeStockData = resource.hmget("Real_time_Stock_Data", symbol);
            List<String> nameStrList = resource.hmget("Stock_Base_Message", symbol);
            if (realTimeStockData.get(0) != null) {
                String s = realTimeStockData.get(0);
                stockRealTimeData = JSON.parseObject(s, StockRealTime.class);
                amp =(stockRealTimeData.getHigh()-stockRealTimeData.getLow())/stockRealTimeData.getPreClose() * 100;
                if (nameStrList.get(0) != null) {
                    String nameStr = nameStrList.get(0);
                    JSONObject stockBaseJson = JSON.parseObject(nameStr);
                    String nameObj = (String) stockBaseJson.get("name");
//                    double sharesObj = stockBaseJson.getDoubleValue("floatShares");
//                    long vol = stockRealTimeData.getVol();
//                    c = new BigDecimal(vol).divide(new BigDecimal(sharesObj),10,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).doubleValue() * 100;
                    stockRealTimeData.setName(nameObj);
                }
            }
            long endSysTime = System.currentTimeMillis();
            //当前时间
            LocalDateTime nowLocalTime = LocalDateTime.now();
            String serverTimeStr = nowLocalTime.format(timeFormatter);
            mData.setServertime(serverTimeStr);
            //当前时间
            LocalDateTime nowDate = LocalDateTime.now();
            String DataStr = nowDate.format(fmTime);
            ArrayList<BuySellEntity.StockBean> stockRealTimeVOList = new ArrayList<>();
            BuySellEntity.StockBean stockRealTimeVO = new BuySellEntity.StockBean();

            stockRealTimeVO.setDate(Long.parseLong(DataStr));
            stockRealTimeVO.setPrice(stockRealTimeData.getNewPrice());
            stockRealTimeVO.setOpen(stockRealTimeData.getOpen());
            stockRealTimeVO.setYclose(stockRealTimeData.getPreClose());
            stockRealTimeVO.setHigh(stockRealTimeData.getHigh());
            stockRealTimeVO.setLow(stockRealTimeData.getLow());
            stockRealTimeVO.setVol(stockRealTimeData.getVol());
            stockRealTimeVO.setAmount(stockRealTimeData.getMoney());
            float Increase = (((stockRealTimeData.getNewPrice() -
                    stockRealTimeData.getPreClose()) / stockRealTimeData.getPreClose())) * 100;
            stockRealTimeVO.setIncrease(Increase);
            stockRealTimeVO.setAmplitude(amp);
            stockRealTimeVO.setExchangerate(c);

            ArrayList<BuySellEntity.StockBean.BuyBean> buyList = new ArrayList<>();
            BuySellEntity.StockBean.BuyBean bu1Bean = new BuySellEntity.StockBean.BuyBean();
            bu1Bean.setPrice(stockRealTimeData.getBuyPrice1());
            bu1Bean.setVol(stockRealTimeData.getBuyVol1() / 100);
            buyList.add(bu1Bean);

            BuySellEntity.StockBean.BuyBean bu2Bean = new BuySellEntity.StockBean.BuyBean();
            bu2Bean.setPrice(stockRealTimeData.getBuyPrice2());
            bu2Bean.setVol(stockRealTimeData.getBuyVol2() / 100);
            buyList.add(bu2Bean);

            BuySellEntity.StockBean.BuyBean bu3Bean = new BuySellEntity.StockBean.BuyBean();
            bu3Bean.setPrice(stockRealTimeData.getBuyPrice3());
            bu3Bean.setVol(stockRealTimeData.getBuyVol3() / 100);
            buyList.add(bu3Bean);

            BuySellEntity.StockBean.BuyBean bu4Bean = new BuySellEntity.StockBean.BuyBean();
            bu4Bean.setPrice(stockRealTimeData.getBuyPrice4());
            bu4Bean.setVol(stockRealTimeData.getBuyVol4() / 100);
            buyList.add(bu4Bean);

            BuySellEntity.StockBean.BuyBean bu5Bean = new BuySellEntity.StockBean.BuyBean();
            bu5Bean.setPrice(stockRealTimeData.getBuyPrice5());
            bu5Bean.setVol(stockRealTimeData.getBuyVol5() / 100);
            buyList.add(bu5Bean);

            stockRealTimeVO.setBuy(buyList);

            ArrayList<BuySellEntity.StockBean.SellBean> sellList = new ArrayList<>();
            BuySellEntity.StockBean.SellBean sellBean1 = new BuySellEntity.StockBean.SellBean();
            sellBean1.setPrice(stockRealTimeData.getSellPrice1());
            sellBean1.setVol(stockRealTimeData.getSellVol1() / 100);
            sellList.add(sellBean1);

            BuySellEntity.StockBean.SellBean sellBean2 = new BuySellEntity.StockBean.SellBean();
            sellBean2.setPrice(stockRealTimeData.getSellPrice2());
            sellBean2.setVol(stockRealTimeData.getSellVol2() / 100);
            sellList.add(sellBean2);

            BuySellEntity.StockBean.SellBean sellBean3 = new BuySellEntity.StockBean.SellBean();
            sellBean3.setPrice(stockRealTimeData.getSellPrice3());
            sellBean3.setVol(stockRealTimeData.getSellVol3() / 100);
            sellList.add(sellBean3);

            BuySellEntity.StockBean.SellBean sellBean4 = new BuySellEntity.StockBean.SellBean();
            sellBean4.setPrice(stockRealTimeData.getSellPrice4());
            sellBean4.setVol(stockRealTimeData.getSellVol4() / 100);
            sellList.add(sellBean4);

            BuySellEntity.StockBean.SellBean sellBean5 = new BuySellEntity.StockBean.SellBean();
            sellBean5.setPrice(stockRealTimeData.getSellPrice5());
            sellBean5.setVol(stockRealTimeData.getSellVol5() / 100);
            sellList.add(sellBean5);


            stockRealTimeVO.setSell(sellList);
            BuySellEntity.StockBean.WeekBean week = new BuySellEntity.StockBean.WeekBean();
            stockRealTimeVO.setWeek(week);
            stockRealTimeVO.setSymbol(symbol);
            stockRealTimeVO.setName(stockRealTimeData.getName());


            stockRealTimeVOList.add(stockRealTimeVO);
            mData.setStock(stockRealTimeVOList);
            mData.setCode(0);
            mData.setMessage("{\"加载版块\":0.0072000000000000007");
            mData.setVersion("HQ.Stock 1.0");
            mData.setTicket((int) (endSysTime - startSysTime));
            mData.setCount(1);
            mData.setStart(0);
            mData.setEnd(20);
        } catch (Exception e) {
            logger.debug("redis中：{}", stockRealTimeData.toString());
            e.printStackTrace();
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
        return mData;
    }

    @Override
    public SplitKLineRes getStockMinData(List<String> symbol) {


        //从外层逐层新建返回的对象
        SplitKLineRes lineResponse = new SplitKLineRes();

        //获取当前系统时间(毫秒)
        long localStartTime = System.currentTimeMillis();
        //当前时间
        LocalDateTime now = LocalDateTime.now();
        String yMdHmsToday = now.format(timeFormatter);
        String yyyyMMddToday = now.format(fmTime);
        long localEndTime = System.currentTimeMillis();//获取当前系统时间(毫秒)
        Jedis resource = null;
        List<HqStockData>hqStockDataList=new ArrayList<>();
        try {
            resource = jedisPool.getResource();

            List<byte[]> recentStockDataList = resource.lrange(Snappy.compress(RecentMinData()+"MD:"+symbol.get(0)), 0, -1);
            if(recentStockDataList.size()>0){
                for (byte[] bytes : recentStockDataList) {
                    String stockData = Snappy.uncompressString(bytes);
                    //小于等于14的是日期标识符
                    if(stockData.length()>14){
                        HqStockData hqStockData =JSON.parseObject(stockData,HqStockData.class);
                         hqStockDataList.add(hqStockData);
                    }
                }
                return pkgStockMinHourData(lineResponse,hqStockDataList,yyyyMMddToday,symbol.get(0),localEndTime,localStartTime,yMdHmsToday);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
        return new SplitKLineRes();
    }

    private SplitKLineRes pkgStockMinHourData(SplitKLineRes lineResponse,List<HqStockData>hqStockDataList ,String yyyyMMddToday,String code,long localEndTime,long localStartTime ,String yMdHmsToday){
        //创建分时数据集合
        ArrayList<StockMinDataVO> stockMinDataVOList = new ArrayList<>();
        ArrayList<StockDayDataVO> stockDayDataVOList = new ArrayList<>();
            try {
                for (HqStockData hqStockData : hqStockDataList){
                    StockMinDataVO stockMinDataVO = new StockMinDataVO();
                    stockMinDataVO.setOpen(hqStockData.getOpen());
                    stockMinDataVO.setHigh(hqStockData.getHigh());
                    stockMinDataVO.setLow(hqStockData.getLow());
                    stockMinDataVO.setVol(hqStockData.getVol());
                    stockMinDataVO.setAvprice(hqStockData.getAvgPrice());
                    stockMinDataVO.setPrice(hqStockData.getNewPrice());
                    stockMinDataVO.setTime(Long.parseLong(String.valueOf(hqStockData.getShortDate()).substring(8, 12)));
                    stockMinDataVO.setAmount(hqStockData.getMoney());
                    stockMinDataVO.setIncrease(hqStockData.getHlPercent().equals("--")?0:Float.valueOf(hqStockData.getHlPercent().replaceAll("%","")));
                    stockMinDataVO.setRisefall(hqStockData.getChange().equals("--")?0:Float.valueOf(hqStockData.getChange()));
                    stockMinDataVOList.add(stockMinDataVO);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        HqStockData hqStockData=hqStockDataList.get(hqStockDataList.size()-1);
            StockDayDataVO stockDayDataVO = new StockDayDataVO();
            String timeStr = String.valueOf(hqStockData).substring(8, 12);//!
            stockDayDataVO.setHigh(hqStockData.getHigh());
            stockDayDataVO.setLow(hqStockData.getLow());
            stockDayDataVO.setLow(hqStockData.getLow());
            stockDayDataVO.setAmount(hqStockData.getMoney());
            stockDayDataVO.setOpen(hqStockData.getOpen());

            stockDayDataVO.setTime(timeStr);
            stockDayDataVO.setYclose(hqStockData.getPreClose());//!
            stockDayDataVO.setDate(yyyyMMddToday);//年月日
            stockDayDataVO.setMinute(stockMinDataVOList);
            stockDayDataVO.setSymbol(code);
            stockDayDataVOList.add(stockDayDataVO);

        lineResponse.setStock(stockDayDataVOList);
        lineResponse.setTicket((int) (localEndTime - localStartTime));
        lineResponse.setServerTime(yMdHmsToday);
        lineResponse.setStart(0);
        lineResponse.setEnd(20);
        lineResponse.setCount(1);
        lineResponse.setMessage("{\"加载版块\":0.0072000000000000007");
        lineResponse.setVersion("HQ.Stock 1.0");
        lineResponse.setCode(0);
        return lineResponse;
    }
    private  String RecentMinData() throws ParseException {
        //如果今天是交易日就是当天 非交易日就是上次的
        Date date=new Date();
        SimpleDateFormat s=new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat s2=new SimpleDateFormat("yyyy-MM-dd");
        //首先确认当天是不是交易日
        TransactionCalendar transactionCalendar=TransactionCalendarMapper.findByCalDate(s.format(date));
        Boolean beforetran=false;
        LocalTime now = LocalTime.now();
        if  (now.isBefore(LocalTime.of(9, 0, 0))){
            beforetran=true;}
        //如果当天是交易日而且早于九点取上一个交易日的数据
        if(transactionCalendar.getIs_open().equals("1")&&!beforetran){

            return s2.format(date);
        }
        else {
            String befordate = TransactionCalendarMapper.getbefor(s.format(date));
            Date da2= s.parse(befordate);
            return s2.format(da2);
        }
    }

}
